home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / misc / update / tpasc302.cpt / TCL Update / New More Files / CFWDesktop.p < prev    next >
Encoding:
Text File  |  1990-05-11  |  14.9 KB  |  558 lines

  1. {****************************************************}
  2. {         CFWDesktop.p}
  3. {}
  4. {        The FWDesktop Class}
  5. {}
  6. {        A Desktop which support floating windows. Floating windows are}
  7. {        always active and remain above all "regular" windows.}
  8. {}
  9. {        SUPERCLASS = CDesktop}
  10. {}
  11. {        Copyright ⌐ 1989, Symantec Corporation.  All rights reserved.            }
  12. {}
  13. {****************************************************}
  14.  
  15. unit CFWDesktop;
  16.  
  17. interface
  18.  
  19.     uses
  20.         SysEqu, TCL, MoreTCL;
  21.  
  22.  
  23. implementation
  24.  
  25.  
  26. {** Class Constant **}
  27.  
  28.     const
  29.         NO_DRAG = $80008000;         { Flag signalling an aborted drag    }
  30.  
  31.  
  32. {****************************************************}
  33. { IFWDesktop}
  34. {}
  35. {        Initialize a FWDesktop object}
  36. {}
  37. {****************************************************}
  38.  
  39.     procedure CFWDesktop.IFWDesktop (aSupervisor: CBureaucrat);
  40.         var
  41.             theFloats: CList;           { Altered by TCL Weaver 1.0 (5/9/90) }
  42.  
  43.     begin
  44.         IDesktop(aSupervisor);        { Initialize superclass            }
  45.  
  46.         new(theFloats);             { Initialize our list of floating   windows }
  47.         itsFloats := theFloats;     { Altered by TCL Weaver 1.0 (5/9/90) }
  48.         itsFloats.IList;
  49.         topFloat := nil;
  50.     end;
  51.  
  52.  
  53. {****************************************************}
  54. { Free (OVERRIDE)}
  55. {}
  56. {        Dispose of a FWDesktop}
  57. {}
  58. {****************************************************}
  59.  
  60.     procedure CFWDesktop.Free;
  61.     begin
  62.         itsFloats.DisposeAll;            { Get rid of floating                }
  63.         itsWindows.DisposeAll;        {   and regular windows            }
  64.  
  65.         ClosePort(macPort);                { Throw out QuickDraw port and all    }
  66.         DisposPtr(Ptr(macPort));        {   assocated data structures        }
  67.  
  68.         inherited Free;                { Pass message on to superclass    }
  69.     end;
  70.  
  71.  
  72. {****************************************************}
  73. { AdjustCursor (OVERRIDE)}
  74. {}
  75. {        Mouse is located where no other object wants to set the cursor shape.}
  76. {        Adjust the shape to the standard arrow cursor}
  77. {}
  78. {****************************************************}
  79.  
  80.     type
  81.         RgnHandlePtr = ^RgnHandle;
  82.  
  83.     procedure Window_DiffContRgn (theWindow: CWindow; mouseRgn: Ptr);
  84.  
  85.             {Subtract content region of floating window from mouseRgn}
  86.  
  87.     begin
  88.         if theWindow.IsVisible then
  89.             DiffRgn(RgnHandlePtr(mouseRgn)^, WindowPeek(theWindow.GetMacPort)^.contRgn, RgnHandlePtr(mouseRgn)^);
  90.     end;
  91.  
  92.  
  93.     procedure CFWDesktop.AdjustCursor (where: Point; mouseRgn: RgnHandle);
  94.     begin
  95.         inherited AdjustCursor(where, mouseRgn);
  96.  
  97.         if topFloat <> nil then
  98.             itsFloats.DoForEach1(Window_DiffContRgn, @mouseRgn);
  99.     end;
  100.  
  101.  
  102. {****************************************************}
  103. { AddWind (OVERRIDE)}
  104. {}
  105. {        Add a window to the desktop}
  106. {}
  107. {****************************************************}
  108.  
  109.     procedure CFWDesktop.AddWind (theWindow: CWindow);
  110.     begin
  111.         if theWindow.IsFloating then
  112.             itsFloats.Prepend(theWindow)
  113.         else
  114.             itsWindows.Add(theWindow);
  115.     end;
  116.  
  117.  
  118. {****************************************************}
  119. { RemoveWind (OVERRIDE)}
  120. {}
  121. {        Remove a window from the desktop}
  122. {}
  123. {****************************************************}
  124.  
  125.     procedure CFWDesktop.RemoveWind (theWindow: CWindow);
  126.     begin
  127.         if theWindow.IsVisible then
  128.             HideWind(theWindow);                { Hide window before discarding it    }
  129.  
  130.         if theWindow.IsFloating then
  131.             itsFloats.Remove(theWindow)
  132.         else
  133.             itsWindows.Remove(theWindow);
  134.     end;
  135.  
  136.  
  137. {****************************************************}
  138. { SelectWind (OVERRIDE)}
  139. {}
  140. {        Select a window by bringing it to the front and making it active}
  141. {}
  142. {****************************************************}
  143.  
  144.     procedure CFWDesktop.SelectWind (theWindow: CWindow);
  145.         var
  146.             aDAIsActive: Boolean;            { TRUE if a DA is the front window    }
  147.             aWindow: CWindow;            { Window object                        }
  148.             oldTop: CWindow;                { Former top regular window        }
  149.             macWPtr: WindowPtr;            { Ptr to Toolbox window record        }
  150.             theDA: WindowPtr;                { Ptr to window record for a DA    }
  151.  
  152.     begin
  153.                                         { Check if a DA is running            }
  154.  
  155.         aDAIsActive := IsSystemWindow(WindowPeek(FrontWindow));
  156.  
  157.                                         { Do nothing if the window is at    }
  158.                                         {   the top of its layer and a DA    }
  159.                                         {   is not active                    }
  160.  
  161.         if ((theWindow = topWindow) or (theWindow = topFloat)) and not aDAIsActive then
  162.             Exit(SelectWind)
  163.         else
  164.             begin
  165.                 if aDAIsActive then
  166.  
  167.                     begin                    { A DA is currently running. Need    }
  168.                                     {   to activate our application.        }
  169.  
  170.                                     { Find our bottom-most window        }
  171.  
  172.                         aWindow := GetBottomWindow;
  173.                         if aWindow = nil then
  174.                             macWPtr := nil
  175.                         else
  176.                             macWPtr := aWindow.macPort;
  177.  
  178.                                         { Put all DAs behind our bottom    }
  179.                                         {   window, maintaining the        }
  180.                                         {   ordering of the DAs            }
  181.  
  182.                         theDA := FrontWindow;
  183.                         while (IsSystemWindow(WindowPeek(theDA))) do
  184.                             begin
  185.                                 SendBehind(theDA, macWPtr);
  186.                                 macWPtr := theDA;
  187.                                 theDA := FrontWindow;
  188.                             end;
  189.                     end;
  190.  
  191.                 if theWindow.IsFloating then
  192.                     begin                        { Select a floating window        }
  193.  
  194.                         if theWindow <> topFloat then
  195.  
  196.                             begin                    { If this isn't the top float ...        }
  197.                                         {   Make it the front window        }
  198.  
  199.                                 BringToFront(theWindow.macPort);
  200.  
  201.                                         {   Update our window list        }
  202.  
  203.                                 itsFloats.BringFront(theWindow);
  204.  
  205.                                 theWindow.Show;            {   Make it visible, if necessary    }
  206.                                 topFloat := theWindow;    {   Mark it as the top float        }
  207.                             end;
  208.  
  209.                     end
  210.                 else if theWindow <> topWindow then
  211.                     begin
  212.                                         { If this isn't the top regular...    }
  213.                         oldTop := topWindow;    {   Save the current top regular    }
  214.  
  215.                         aWindow := CWindow(itsFloats.LastItem);
  216.                         if aWindow = nil then
  217.                                         {   Put it in front if there are    }
  218.                                         {     no floating windows            }
  219.  
  220.                             BringToFront(theWindow.macPort)
  221.                         else
  222.                                         {   Otherwise, put it behind the    }
  223.                                         {     bottom floating window        }
  224.  
  225.                             BringBehind(theWindow.macPort, aWindow.macPort);
  226.  
  227.                                         {   Update our window list        }
  228.  
  229.                         itsWindows.BringFront(theWindow);
  230.  
  231.                         theWindow.ShowOrHide(TRUE);        {   Make it visible, if necessary    }
  232.  
  233.                         topWindow := theWindow;            {   Mark it as the top regular    }
  234.  
  235.                         if aDAIsActive then
  236.                             begin
  237.                                 if oldTop <> nil then
  238.                                     begin
  239.                                         HiliteWindow(oldTop.macPort, FALSE);
  240.                                         CDirector(oldTop.itsSupervisor).active := FALSE;
  241.                                     end;
  242.                                 CDirector(topWindow.itsSupervisor).active := TRUE;
  243.  
  244.                             end
  245.                         else
  246.                             begin
  247.  
  248.                                 if oldTop <> nil then         {   Deactivate the former top    }
  249.                                                 {     regular window                }
  250.                                     oldTop.Deactivate;
  251.  
  252.                                 topWindow.Activate;        {   Activate the new top window    }
  253.                             end;
  254.                     end;
  255.  
  256.                 LongPtr(CurActivate)^ := longint(nil);     { Nuke any pending activate event    }
  257.             end;
  258.     end;
  259.  
  260.  
  261. {****************************************************}
  262. { ShowWind (OVERRIDE)}
  263. {}
  264. {        Make a window visible on the desktop}
  265. {}
  266. {****************************************************}
  267.  
  268.     procedure CFWDesktop.ShowWind (theWindow: CWindow);
  269.     begin
  270.         if theWindow.IsFloating then
  271.             begin
  272.                 ShowHide(theWindow.macPort, TRUE);
  273.                 theWindow.Activate;
  274.                 CalcTopFloat;
  275.             end
  276.         else
  277.             inherited ShowWind(theWindow);
  278.     end;
  279.  
  280.  
  281. {****************************************************}
  282. { HideWind (OVERRIDE)}
  283. {}
  284. {        Make a window invisible on the desktop}
  285. {}
  286. {****************************************************}
  287.  
  288.     procedure CFWDesktop.HideWind (theWindow: CWindow);
  289.     begin
  290.         if theWindow.IsFloating then
  291.             begin
  292.                 ShowHide(theWindow.macPort, FALSE);
  293.                 if theWindow = topFloat then
  294.                     CalcTopFloat;
  295.             end
  296.         else
  297.             inherited HideWind(theWindow);
  298.     end;
  299.  
  300.  
  301. {****************************************************}
  302. { DragWind (OVERRIDE)}
  303. {}
  304. {        Drag a window on the desktop}
  305. {}
  306. {****************************************************}
  307.  
  308.     procedure CFWDesktop.DragWind (theWindow: CWindow; macEvent: EventRecord);
  309.         var
  310.             savePort: GrafPtr;                { The current QD port                }
  311.             macWindow: WindowPtr;        { Toolbox window pointer            }
  312.             corner: Point;                    { Top left corner of window            }
  313.             dragBox: Rect;                    { Where window may be dragged    }
  314.             newLoc: longint;                { New location after drag            }
  315.             hDrag: integer;                    { Distance dragged horizontally        }
  316.             vDrag: integer;                    { Distance dragged vertically        }
  317.  
  318.     begin
  319.         if (theWindow <> topWindow) and (theWindow <> topFloat) and (BAND(macEvent.modifiers, cmdKey) = 0) then
  320.  
  321.                                         { Drag for an underlying window    }
  322.                                         {   without the command key being    }
  323.                                         {   pressed. Select window before    }
  324.                                         {   performing the drag.                }
  325.             SelectWind(theWindow);
  326.  
  327.         if not StillDown then             { Take a quick exit if the mouse    }
  328.             Exit(DragWind);                {   has already been released    }
  329.  
  330.         GetPort(savePort);                { Save the current port            }
  331.  
  332.                                         { Find Global coords of the top    }
  333.                                         {   left corner of the window    }
  334.  
  335.         macWindow := WindowPtr(theWindow.GetMacPort);
  336.         SetPort(macWindow);
  337.         corner := topLeft(macWindow^.portRect);
  338.         LocalToGlobal(corner);
  339.  
  340.         SetPort(macPort);                { Use desktop's port                    }
  341.         PenNormal;                        { Use standard pen characteristics    }
  342.  
  343.         dragBox := bounds;                { Don't allow drag too close to    }
  344.                                         {   the edge of the screen        }
  345.  
  346.         InsetRect(dragBox, DRAG_MARGIN, DRAG_MARGIN);
  347.  
  348.                                         { Drag dotted outline of window    }
  349.  
  350.         CopyRgn(WindowPeek(macWindow)^.strucRgn, gUtilRgn);
  351.         newLoc := DragGrayRgn(gUtilRgn, macEvent.where, dragBox, dragBox, 0, nil);
  352.         hDrag := LoWord(newLoc);
  353.         vDrag := HiWord(newLoc);
  354.  
  355.                                         { If a drag actually occurred, put    }
  356.                                         {   window at new location            }
  357.  
  358.         if (newLoc <> NO_DRAG) and ((hDrag <> 0) or (vDrag <> 0)) then
  359.             MoveWindow(macWindow, LoWord(newLoc) + corner.h, HiWord(newLoc) + corner.v, FALSE);
  360.  
  361.         SetPort(savePort);                { Restore the original port            }
  362.     end;
  363.  
  364.  
  365. {****************************************************}
  366. { Show (OVERRIDE)}
  367. {}
  368. {        Make a Desktop visible by showing all its windows}
  369. {}
  370. {****************************************************}
  371.  
  372.     procedure CFWDesktop.Show;
  373.     begin
  374.         if not visible then
  375.             begin                        { Do nothing if already visible    }
  376.                 visible := TRUE;
  377.                 itsFloats.DoForEach(Window_Show);
  378.                 itsWindows.DoForEach(Window_Show);
  379.             end;
  380.     end;
  381.  
  382.  
  383. {****************************************************}
  384. { Hide (OVERRIDE)}
  385. {}
  386. {        Make a Desktop invisible by hiding all its windows}
  387. {}
  388. {****************************************************}
  389.  
  390.     procedure CFWDesktop.Hide;
  391.     begin
  392.         if visible then
  393.             begin                        { Do nothing if already invisible    }
  394.                 visible := FALSE;
  395.                 itsWindows.DoForEach(Window_Hide);
  396.                 itsFloats.DoForEach(Window_Hide);
  397.             end;
  398.     end;
  399.  
  400.  
  401. {****************************************************}
  402. { Activate (OVERRIDE)}
  403. {}
  404. {        Activate a desktop by activating all floating windows and the}
  405. {        top regular window}
  406. {}
  407. {****************************************************}
  408.  
  409.     procedure CFWDesktop.Activate;
  410.     begin
  411.         if not active then
  412.             begin                        { Do nothing if already active        }
  413.                 active := TRUE;
  414.                 itsFloats.DoForEach(Window_Activate);
  415.                 if topWindow <> nil then
  416.                     topWindow.Activate;
  417.             end;
  418.     end;
  419.  
  420.  
  421. {****************************************************}
  422. { Deactivate (OVERRIDE)}
  423. {}
  424. {        Deactivate a desktop by deactivating all floating windows and the}
  425. {        top regular window}
  426. {}
  427. {****************************************************}
  428.  
  429.     procedure CFWDesktop.Deactivate;
  430.     begin
  431.         if active then
  432.             begin                        { Do nothing if already inactive    }
  433.                 active := FALSE;
  434.                 itsFloats.DoForEach(Window_Deactivate);
  435.                 if topWindow <> nil then
  436.                     topWindow.Deactivate;
  437.             end;
  438.     end;
  439.  
  440.  
  441. {****************************************************}
  442. { GetBottomWindow (OVERRIDE)}
  443. {}
  444. {        Return the Desktop's bottom-most window (not including DAs).}
  445. {}
  446. {****************************************************}
  447.  
  448.     function CFWDesktop.GetBottomWindow: CWindow;
  449.         var
  450.             bottomWindow: CWindow;
  451.  
  452.     begin
  453.         bottomWindow := inherited GetBottomWindow;
  454.  
  455.         if bottomWindow = nil then
  456.             GetBottomWindow := CWindow(itsFloats.LastItem)
  457.         else
  458.             GetBottomWindow := bottomWindow;
  459.     end;
  460.  
  461.  
  462. {****************************************************}
  463. { CalcTopFloat}
  464. {}
  465. {        Set topFloat to the first visible window in itsFloats (if any). }
  466. {}
  467. {****************************************************}
  468.  
  469.     procedure CFWDesktop.CalcTopFloat;
  470.     begin
  471.         topFloat := CWindow(itsFloats.FirstSuccess(Window_IsVisible));
  472.     end;
  473.  
  474.  
  475. {****************************************************}
  476. { Cleanup (OVERRIDE)}
  477. {}
  478. {        Move THINK Pascal's windows behind our application's windows. }
  479. {}
  480. {        If we are running in the THINK Pascal environment, one or more }
  481. {        of THINK Pascal's windows may (from our viewpoint) "suddenly" }
  482. {        appear directly behind our top floating window.  This happens if }
  483. {        the user clicks on a Pascal window, or if the user breaks into the }
  484. {        source-level debugger, opens up some windows, and resumes }
  485. {        execution.  In these situations, THINK Pascal takes care of bringing }
  486. {        our frontmost (floating) window back to the top }
  487. {        (when CApplication.Run calls FrontWindow), but we are }
  488. {        responsible for bringing the rest of our floating windows and our }
  489. {        top non-floating window forward.  If we are NOT running in the }
  490. {        THINK Pascal environment, this code will have no ill effects. }
  491. {}
  492. {****************************************************}
  493.  
  494.     procedure CFWDesktop.Cleanup;
  495.  
  496.         var
  497.             testWindow, bottomFloat, lastWindowMoved: WindowPeek;
  498.  
  499.     begin
  500.  
  501. { No cleanup necessary if there are no floating windows. }
  502.  
  503.         if itsFloats.FirstItem <> nil then        { We use itsFloats.FirstItem instead }
  504.                                                 { of topFloat because if topFloat = nil, }
  505.                                                 { that means there are no VISIBLE }
  506.                                                 { floating windows;  there still may be }
  507.                                                 { an invisible floating window, which }
  508.                                                 { THINK Pascal would consider our }
  509.                                                 { application's frontmost window. }
  510.  
  511.             begin
  512.                 lastWindowMoved := nil;    { We will use this var to preserve the ordering }
  513.                                         { of the Pascal windows. }
  514.  
  515.                 if topWindow <> nil then
  516.  
  517. { If there are THINK Pascal windows behind the top floating window, }
  518. { then send the Pascal windows behind the top non-floating window }
  519. { (topWindow). }
  520.  
  521.                     repeat
  522.                         testWindow := WindowPeek(CWindow(itsFloats.FirstItem).GetMacPort)^.nextWindow;
  523.                         if testWindow^.windowKind >= pascalKind then
  524.                             begin
  525.                                 if lastWindowMoved = nil then
  526.                                     SendBehind(WindowPtr(testWindow), topWindow.macPort)
  527.                                 else
  528.                                     SendBehind(WindowPtr(testWindow), WindowPtr(lastWindowMoved));
  529.                                 lastWindowMoved := testWindow;
  530.                             end;
  531.                     until testWindow^.windowKind < pascalKind
  532.  
  533.                 else
  534.  
  535. { There are no visible non-floating windows.  If there are THINK Pascal windows }
  536. { behind the top floating window, then send the }
  537. { Pascal windows behind the bottom floating window. }
  538.  
  539.                     begin
  540.                         bottomFloat := WindowPeek(CWindow(itsFloats.LastItem).GetMacPort);
  541.                         if itsFloats.FirstItem <> itsFloats.LastItem then
  542.                             repeat
  543.                                 testWindow := WindowPeek(CWindow(itsFloats.FirstItem).GetMacPort)^.nextWindow;
  544.                                 if testWindow^.windowKind >= pascalKind then
  545.                                     begin
  546.                                         if lastWindowMoved = nil then
  547.                                             SendBehind(WindowPtr(testWindow), WindowPtr(bottomFloat))
  548.                                         else
  549.                                             SendBehind(WindowPtr(testWindow), WindowPtr(lastWindowMoved));
  550.                                         lastWindowMoved := testWindow;
  551.                                     end;
  552.                             until testWindow^.windowKind < pascalKind;
  553.                     end;
  554.             end;
  555.     end;
  556.  
  557.  
  558. end.